#include <iostream>
#include <algorithm>

using namespace std;


// a、内置类型之间
// b、内置类型和自定义类型之间
// c、自定义类型和自定义类型之间

/* ———————————— a. 内置类型——————————————————*/
 //1、隐式类型转换    整形之间/整形和浮点数之间
 //2、显示类型的转换  指针和整形、指针之间

//int main()
//{
//	int i = 1;
//	// 隐式类型转换
//	double d = i;
//	printf("%d, %.2f\n", i, d);
//
//	int* p = &i;
//	// 显示的强制类型转换
//	int address = (int)p;
//	printf("%p, %d\n", p, address);
//
//	return 0;
//}



/* ———————————— b. 内置类型和自定义类型之间——————————————————*/
//1、自定义类型 = 内置类型  -> 构造函数支持 （单参数和多参数的隐式类型转换时通过构造函数来支持的）
// 2、内置类型 = 自定义类型 （自定义类型，转化为内置类型）

//class A {
//public:
//	//explicit A(int a) //禁止隐式类型转换
//	A(int a)
//		:_a1(a)
//		, _a2(a)
//	{}
//	A(int a1,int a2)
//		:_a1(a1)
//		, _a2(a2)
//	{}
//
//	//int operator()() 中()被仿函数占用了，不能用
//	// operator 类型实现，无返回类型
//  // 自定义类型转换为内置类型
//	//explicit operator int()
//	operator int()
//	{
//		return _a1 + _a2;
//	}
//
//private:
//	int _a1 = 1;
//	int _a2 = 1;
//};
//
//int main()
//{
//	//单参数的隐式类型转换
//	//在其对应的构造函数那加了explicit关键字，就不支持隐式类型转换
//	//A aa1 = 1; //单参数类型转换为自定义类型，靠构造函数转的
//	A aa1 = A(1);//但是还是支持转换
//
//	//多参数的隐式类型转换
//	A aa2 = { 2,2 };
//	const A& aa3 = { 2,2 };
//
//	//int z = aa1.operator int();//本质是这个
//	int x = aa1; //隐式类型转换
//	int y = (int)aa2; //显式类型转换
//	cout << x << " " << y << endl;
//
//	//智能指针的条件逻辑判断
//
//	std::shared_ptr<int> foo;
//	std::shared_ptr<int> bar(new int(34));
//
//	//if (foo.operator bool())
//	if (foo)
//		std::cout << "foo points to " << *foo << '\n';
//	else 
//		std::cout << "foo is null\n";
//
//	if (bar)
//		std::cout << "bar points to " << *bar << '\n';
//	else
//		std::cout << "bar is null\n";
//
//	return 0;
//}




/* ———————————— c. 自定义类型和自定义类型之间——————————————————*/
// c、自定义类型和自定义类型之间 -- 对应的构造函数支持

//class A {
//public:
//	A(int a)
//		:_a1(a)
//		, _a2(a)
//	{}
//	A(int a1, int a2)
//		:_a1(a1)
//		, _a2(a2)
//	{}
//
//	int get()const
//	{
//		return _a1 + _a2;
//	}
//
//private:
//	int _a1 = 1;
//	int _a2 = 1;
//};
//
//
//class B
//{
//public:
//	B(int b)
//		:_b1(b)
//	{}
//
//	B(const A&aa)
//		:_b1(aa.get())
//	{}
//
//private:
//	int _b1 = 1;
//};
//
//#include "List.h"
//int main()
//{
//	A aa1(1);
//	B bb1(1);
//
//	//aa1 = bb1;
//	bb1 = aa1;
//	B& ref1 = bb1;
//
//	//B& ref2 = aa1;
//	const B& ref2 = aa1;
//
//	bit::list<int> l1 = { 1,2,3,4 };
//	//权限的缩小？ 权限的缩小和放大，仅限于const的指针和引用
//	// 不是权限缩小，这里是类型转换
//	bit::list<int>::const_iterator cit = l1.begin();
//	while (cit != l1.end())
//	{
//		cout << *cit << " ";
//		++cit;
//	}
//	cout << endl;
//
//
//	return 0;
//}


/* —————————— 四种命名的强制类型转换操作符——————————*/

//int main()
//{
//	// 1.对应隐式类型转换 -- 数据的意义没有改变
//	double d = 12.34;
//	int a = static_cast<int> (d);
//	//cout << a << endl;
//
//	// 2.对应强制类型转换 -- 数据的意义已经发生改变
//	//int* p1 = static_cast<int*>(a);
//	int* p1 = reinterpret_cast<int*>(a);
//
//	// 3.也对应强制类型转换中有风险的去掉const属性
//	//常变量
//	//const int b = 2;
//
//	 // 我们可以使用volatile 来打印我们希望的结果 3 
//	//当要求使用 volatile 声明的变量的值的时候，系统总是重新从它所在的内存读取数据
//	//即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存
//	volatile const int b = 2; 
//
//	//int* p2 = (int*)&b; //上下两种方式效果等同
//	int* p2 = const_cast<int*>(&b);
//	*p2 = 3;
//
//	const int c = b; //在这里很明显可以看到 b 的具体值
//
//	// b 其实在内存中已经修改为3，比如在监视窗口下就是3，但是去读的时候已经变成常量2了
//	cout << b << " " <<  * p2 << " " << c << endl;
//
//	return 0;
//}


/*————————  dynamic_cast ———————— */

class A
{
public:
	virtual void f() {}

	int _a = 1;
};
class B : public A
{
public:
	int _b = 2;
};

void test()
{
	B b;
	A a = b;
	A& ra = b;

	double d = 1.1;
	const int& i = d;
}


void fun(A* pa)
{
	//// 指向父类转换时有风险的，后续访问存在越界访问的风险
	//// 指向子类转换时安全
	//B* pb1 = (B*)pa;
	//cout << "pb1: " << pb1 << endl;
	//cout << "pb1->_a: " << pb1->_a << endl;
	//cout << "pb1->_b: " << pb1->_b << endl;

	//pb1->_a++;
	//pb1->_b++;
	//cout << "pb1->_a: " << pb1->_a << endl;
	//cout << "pb1->_b: " << pb1->_b << endl;


	// dynamic_cast会先检查是否能转换成功(指向子类对象)，能成功则转换，
	// (指向父类对象)不能则返回NULL

	B* pb1 = dynamic_cast<B*>(pa);
	if (pb1) //先判断是否为空
	{
		cout << "pb1:" << pb1 << endl;
		cout << "pb1->_a: " << pb1->_a << endl;
		cout << "pb1->_b: " << pb1->_b << endl;
		pb1->_a++;
		pb1->_b++;
		cout << "pb1->_a: " << pb1->_a << endl;
		cout << "pb1->_b: " << pb1->_b << endl;
	}
	else
	{
		cout << "转换失败" << endl;
	}

	B* pb2 = static_cast<B*>(pa);
	B* pb3 = dynamic_cast<B*>(pa);
	cout << "pb2: " << pb2 << endl;
	cout << "pb3: " << pb3 << endl;

}

int main()
{
	A a;
	B b;
	fun(&a);
	fun(&b);
	return 0;
}